﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Windows.Forms;
using pub.Functions;
using todo.Interop;
using todo.Model;

namespace todo
{
    internal class TodoApi
    {
        public static TodoApi Instance;

        private WebBrowser _www;

        private volatile Todo _activeTodo;
        private int _lastActiveTodoChangeCounter = -1;
        private int _lastActiveTodoIdleCount = -1;

        private int _docChangeCounter;

        public int DocChangeCounter
        {
            get { return _docChangeCounter; }
            set
            {
                Console.WriteLine("..");
                _docChangeCounter = value;
            }
        }

        private IDictionary<string, string> _namedColors = new Dictionary<string, string> {
                {"yellow", "#fafad2"},
                {"red", "#f2dede"},
                {"green", "#dff0d8"},
                {"blue", "#c4e3f3"},
                {"cyan", "#e0ffff"},
                {"gray", "#f9f9f9"},
        };

        public TodoApi(WebBrowser www)
        {
            _www = www;
        }

        public bool Ready
        {
            get
            {
                return _www.Visible &&
                       _www.Document != null &&
                       _www.ReadyState == WebBrowserReadyState.Complete;
            }
        }

        private object Call(string fnName, params object[] args)
        {
            if (args == null)
            {
                args = new object[0];
            }
            var result = _www.Document.InvokeScript(fnName, args);
            return result;
        }

        public void Cut()
        {
            Call("todo_cut");
        }

        public void Copy()
        {
            Call("todo_copy");
        }

        public void Paste(string todosHtml, string pasteType)
        {
            Call("todo_paste", todosHtml, pasteType);
        }

        public void PasteText(string text)
        {
            Call("todo_pasteText", text);
        }

        public void Delete()
        {
            Call("todo_delete");
        }

        public bool CanUndo()
        {
            if (!Ready)
            {
                return false;
            }
            return (bool) Call("todo_canUndo");
        }

        public void Undo()
        {
            Call("todo_undo");
        }

        public bool CanRedo()
        {
            if (!Ready)
            {
                return false;
            }
            return (bool) Call("todo_canRedo");
        }

        public void Redo()
        {
            Call("todo_redo");
        }

        public Todo ActiveTodo
        {
            get
            {
                if ((_activeTodo == null && _lastActiveTodoIdleCount != App.IdleCount) ||
                    _lastActiveTodoChangeCounter != DocChangeCounter)
                {
//                    Debug.Print("QueryActiveTodo@" + DateTime.Now);
                    QueryActiveTodo();
                    _lastActiveTodoChangeCounter = DocChangeCounter;
                    _lastActiveTodoIdleCount = App.IdleCount;
                }
//                if (_lastActiveTodoIdleCount == App.IdleCount)
//                {
//                    Console.WriteLine("?");
//                }
                return _activeTodo;
            }
            set { _activeTodo = value; }
        }

        public bool IsActiveTodoActive
        {
            get
            {
                if (!Ready)
                {
                    return false;
                }
                var todo = ActiveTodo;
                if (todo == null)
                {
                    return false;
                }
                return todo.Active == 1;
            }
        }

        public bool IsActiveTodoChecked
        {
            get
            {
                if (!Ready)
                {
                    return false;
                }
                var todo = ActiveTodo;
                if (todo == null)
                {
                    return false;
                }
                return todo.Checked == 1;
            }
        }

        private void QueryActiveTodo()
        {
            if (!Ready)
            {
                _activeTodo = null;
                return;
            }
            var todoResult = new TodoResult();
            Call("todo_getActiveTodo", todoResult);
            _activeTodo = todoResult.Todo;
            //Debug.Print("##################### Got ActiveTodo: " + _activeTodo.Title);
        }

        public void ToggleActive()
        {
            Call("todo_toggleActive");
        }

        public void ToggleChecked()
        {
            Call("todo_toggleChecked");
        }

        public void SetPriority(int priority)
        {
            Call("todo_setPriority", priority);
        }

        public int? GetPriority()
        {
            if (!Ready)
            {
                return null;
            }
            var todo = ActiveTodo;
            if (todo == null)
            {
                return null;
            }
            return todo.Priority;
        }

        public void ToggleTag(string tagName)
        {
//            MessageBox.Show(tagName);
            Call("todo_toggleTag", tagName);
        }

        public int? GetColor()
        {
            if (!Ready)
            {
                return null;
            }
            var todo = ActiveTodo;
            if (todo == null)
            {
                return null;
            }
            var sColor = todo.Color;
            if (string.IsNullOrEmpty(sColor))
            {
                return null;
            }
            if (sColor[0] != '#')
            {
                sColor = _namedColors[sColor];
            }
            return ColorTranslator.FromHtml(sColor).ToArgb();
        }

        public void SetColor(int? color)
        {
            var sColor = "";
            if (color.HasValue)
            {
                sColor = ColorTranslator.ToHtml(Color.FromArgb(color.Value));
            }
            Call("todo_setColor", sColor);
        }

        public bool? IsBold()
        {
            if (Ready && ActiveTodo != null)
            {
                return ActiveTodo.DisplayStyle.HasFlag(DisplayStyle.Bold);
            }
            return null;
        }

        public void ToggleBold()
        {
            Call("todo_toggleBold");
        }

        public bool? IsItalic()
        {
            if (Ready && ActiveTodo != null)
            {
                return ActiveTodo.DisplayStyle.HasFlag(DisplayStyle.Italic);
            }
            return null;
        }

        public void ToggleItalic()
        {
            Call("todo_toggleItalic");
        }

        public bool? IsUnderline()
        {
            if (Ready && ActiveTodo != null)
            {
                return ActiveTodo.DisplayStyle.HasFlag(DisplayStyle.Underline);
            }
            return null;
        }

        public void ToggleUnderline()
        {
            Call("todo_toggleUnderline");
        }

        public bool? IsEditing()
        {
            if (!Ready || ActiveTodo == null)
            {
                return null;
            }
            return (bool) Call("todo_isEditing");
        }

        public void BeginEdit()
        {
            Call("todo_beginEdit");
        }

        public void EndEdit()
        {
            Call("todo_endEdit");
        }

        public void AddAfter()
        {
            Call("todo_addAfter");
        }

        public void AddChild()
        {
            Call("todo_addChild");
        }

        public void Add()
        {
            Call("todo_add");
        }

        public void ExpandAll()
        {
            Call("todo_expandAll");
        }

        public void CollapseAll()
        {
            Call("todo_collapseAll");
        }

        public List<Todo> GetSelectedTodos()
        {
            var todosResult = new TodosResult();
            Call("todo_getSelectedTodos", todosResult);
            var todos = todosResult.Todos;
            if (todos == null)
            {
                return new List<Todo>();
            }
            return todos.GetList();
        }

        public string GetSelectedText()
        {
            return (string) Call("todo_getSelectedText");
        }

        public void SetGridLineVisible(bool visible)
        {
            Call("todo_setGridLineVisible", visible);
        }

        public void SetTreeLineVisible(bool visible)
        {
            Call("todo_setTreeLineVisible", visible);
        }

        public void SetHeaderVisible(bool visible)
        {
            Call("todo_setHeaderVisible", visible);
        }

        public void Archive()
        {
            //xx
        }

        public void SetTheme(string themeName)
        {
            Call("todo_setTheme", themeName);
        }

        public bool HasSelection
        {
            get
            {
                if (!Ready || ActiveTodo == null)
                {
                    return false;
                }
                return (bool) Call("todo_hasSelection");
            }
        }

        public void SetReminder()
        {
            Call("todo_setReminder");
        }

        //\n separated
        public void SetActiveTodo(string pathTitles)
        {
            Call("todo_setActiveTodo", pathTitles);
        }
    }
}